import java.awt.AWTException;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JApplet;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.filechooser.FileSystemView;
class Rocket implements Drawable, MouseMotionListener, MouseListener {
	short x;
	short y;
	static final byte MAX_BOOST = 100;
	byte boost = MAX_BOOST;
	boolean inboost = false;
	private int SPEED;
	short mousex;
	short health = 0;
	boolean dead;
	Asteroid shooting;
	short shootingFor;
	public static BufferedImage baseImg = null; {
		try {
			baseImg = ImageIO.read(Rocket.class.getResource("rocket.gif"));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public Rocket() {
		reset();
	}
	public void reset() {
		x = 40;
		y = (short) ( Level.level.getHeight()-baseImg.getHeight()/2-5);
		dead = false;
		shooting = null;
		shootingFor = 0;
		SPEED = 3;
	}
	
	public static BufferedImage rotateImage(Image img, short degrees) {
		int size =(int) (Math.max(img.getWidth(null), img.getHeight(null)) * 2);
		BufferedImage rotated = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
		Graphics2D graphics = (Graphics2D) rotated.getGraphics();
		graphics.translate(size/2, size/2);
		graphics.rotate(Math.toRadians(degrees));
		graphics.drawImage(img, -size/4, -size/4, null);
		return rotated;
	}
	public void die() {
		dead = true;
		System.out.println("~~~DIED~~~");
	}
	public boolean isCollidingWith(Asteroid asteroid) {
		return  Math.abs(asteroid.y - y) < asteroid.size/2 + baseImg.getHeight()/2 && Math.abs(asteroid.x - x) < asteroid.size/2 + baseImg.getWidth()/2 &&  Math.sqrt(square(x - asteroid.x) + square(y - asteroid.y)) < asteroid.size/2 + baseImg.getHeight()/2;
	}
	public int square(int i) {
		return i*i;
	}
	short addX;
	boolean fw;
	public void update() {
			boost += inboost ? -(1.5 / Level.level.fps) : boost <= MAX_BOOST ? Math.ceil(Level.level.fps/10) : 0;
		boolean fw = mousex-x > 0;
		addX = (short) ((fw?1:-1) * Math.sqrt(Math.pow((fw? 1 : -1) * (mousex-x),3/SPEED)));
		x += addX;
		if(!dead)
			y -= (short) ((y -  ((Level.level.getHeight()-baseImg.getHeight()/2) - (inboost?50:20)))/2);
		}
	public void drawOn(Graphics2D g) {
		g.drawImage(rotateImage(baseImg, addX),(x - baseImg.getWidth()), y - baseImg.getHeight(), null);
		if(shooting != null && shooting.size <= 3)
			shooting = null;
		else if(shooting != null){
			shootingFor += 1/Level.level.fps;
			shooting.shrink();
			g.setColor(new Color(Star.random.nextInt(30), 100 + Star.random.nextInt(155), Star.random.nextInt(30)));
			g.setStroke(new BasicStroke(3));
			g.drawLine(x + addX, y - baseImg.getHeight()/2, shooting.x, shooting.y);
		}
	}
	public void mouseDragged(MouseEvent e) {
		mousex = (short) e.getX();
	}
	public void mouseMoved(MouseEvent e) {
		mousex = (short) e.getX();
	}
	@Override
	public void mouseClicked(MouseEvent e) {
	}
	@Override
	public void mousePressed(MouseEvent e) {
		if(e.getButton() == MouseEvent.BUTTON1 && ! Level.level.paused) {
			Asteroid zap = Level.level.getAsteroidAt(e.getX(), e.getY());
			if(shooting == null && zap != null && !dead) {
				shooting = zap;
			}
		} else if (e.getButton() == MouseEvent.BUTTON2)
			Level.level.paused = !Level.level.paused; 
		else if (e.getButton() == MouseEvent.BUTTON3)
			inboost = true;
	}
	@Override
	public void mouseReleased(MouseEvent e) {
		shooting = null;
		shootingFor = 0;
		if (e.getButton() == MouseEvent.BUTTON3)
			inboost = false;
	}
	@Override
	public void mouseEntered(MouseEvent e) {
		
	}
	@Override
	public void mouseExited(MouseEvent e) {
		
	}
}
public class Level extends JPanel implements Runnable, KeyListener {
	short fps = 20;
	public Rocket rocket;
	public byte difficulty = 1;
	private boolean running = true;
	public static final Color BACKGROUND_COLOR = new Color(15, 3, 39);
	private String name;
	
	private Star[] stars = new Star[10];
	private Asteroid[] asteroids = new Asteroid[10];
	private long tp = 0;
	protected boolean dead = false;
	protected int deadY = getHeight();
	public int crystalsCollected = 0;
	public static Level level;
	boolean paused = false;
	boolean lolMode = false;
	public BufferedImage frame;
	public static final Font barFont = new Font("Droid Sans, DejaVu Sans, Comic Sans", Font.BOLD, 15);
	public void reset() {
		System.out.println("RESET");
		rocket.reset();
		for(int i = 0; i < asteroids.length; i ++)
			asteroids[i] = null;
		for(int i = 0; i < stars.length; i ++)
			stars[i] = null;
		dead = false;
		running = true;
		crystalsCollected = 0;
		tp = 0;
	}
	public static byte getAsteroidsOnScreen(Level lvl) {
		return (byte) Math.floor(lvl.getWidth() / 100 / lvl.difficulty);
	}
	public Level(String name) {
		level = this;
		addKeyListener(this);
		setFocusable(true);
		System.out.println("Focus:"+requestFocusInWindow());
		this.name = name;
		new Thread(new Runnable() {
			public void run() {
				setSize(486, 648);
				rocket = new Rocket();
				for(int i = 0; i < stars.length; i++) {
					stars[i] = Star.generateRandom();
				}
				addMouseMotionListener(rocket);
				addMouseListener(rocket);
				new Thread(Level.this).start();
			}
		}).start();
		}
	public void changeFPS(short fps) {
		this.fps = fps;
	}
	final static String PAUSED = "PAUSED";
	public void repaintStuff() {
		setBounds(0, 0, getParent().getWidth(), getParent().getHeight());
		if(frame == null || frame.getWidth() != getWidth() || frame.getHeight() != getHeight())
			frame = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_3BYTE_BGR);
		Graphics2D g = (Graphics2D) frame.getGraphics();
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
				RenderingHints.VALUE_ANTIALIAS_ON);
		g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 
				RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		g.setColor(BACKGROUND_COLOR);
		g.fillRect(0, 0, getWidth(), getHeight());
		for(int i = 0; i < stars.length; i++) {
			if(stars[i] != null && stars[i].shouldClose) {
				stars[i] = Star.generateRandom();
			}
			if(stars[i] != null && !paused)
				stars[i].update();
			if(stars[i] != null)
				stars[i].drawOn(g);
		}
		if(dead) {
			final Composite G = g.getComposite();
		    g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f));
		    g.setColor(Color.GRAY);
		    g.fillRoundRect((int) (getWidth() * 0.15), (int) (getHeight() * 0.15), (int) (getWidth() * 0.70), (int) (getHeight() * 0.70), 30, 30);
		    g.setColor(Color.WHITE);
		    g.setFont(barFont.deriveFont(Font.BOLD));
		    String txt = "Your time: " + getTime();
		    g.drawString(txt, (getWidth() - g.getFontMetrics().stringWidth(txt))/2, getHeight() / 4);
		    txt = "Crystals collected: " + crystalsCollected;
		    g.drawString(txt, (getWidth() - g.getFontMetrics().stringWidth(txt))/2, getHeight() / 4 + 30);
		    txt = "Going to main menu...";
		    g.setComposite(G);
	    } 
		if(!paused)
			rocket.update();
		rocket.drawOn(g);
		byte astOnScreen = getAsteroidsOnScreen(this);
		Asteroid a;
		System.out.println(asteroids.length);
		for(int i = 0; i < asteroids.length; i++) {
			a = asteroids[i];
			if(a != null)
				System.out.println(a.x + a.y);
			if(a != null && a.crystalised && rocket.isCollidingWith(a)) {
				crystalsCollected++;
				rocket.boost +=5;
				a = null;
			} else if(i < astOnScreen && (a == null || a.shouldClose))
				a = asteroids[i] = Asteroid.generateRandom(lolMode);
			else if(a!= null && rocket.isCollidingWith(a) && ! rocket.dead) {
				rocket.die();
				dead = true;
				running = false;
				getParent().remove(Level.this);
				return;
			}
			if(a != null) {
				a.drawOn(g);
				if(!paused)
					a.update();
			}
		}
		drawLevelBarOn(g);
		if(paused && !dead) {
			g.setFont(barFont.deriveFont(30));
			g.drawString(PAUSED, getWidth()/2 - g.getFontMetrics().stringWidth(PAUSED)/2, getHeight()/2 - g.getFontMetrics().getHeight()/2);
		}
		getGraphics().drawImage(frame, 0, 0, this);
	}
	final static String ASTDES = "Crystals: ";
	final static String TIME = "Time: ";
	String time;
	final static String BOOST_BAR = "BOOST BAR";
	private StringBuffer tempString = new StringBuffer();
	public void drawLevelBarOn(Graphics2D g) {
		final Composite c = g.getComposite();
		g.setFont(barFont);
		int wtdt = g.getFontMetrics().getHeight()-3;
		g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f));
		g.setColor(Color.BLUE);
		g.fillRect(0, 0, getWidth(), 24);
		g.setFont(barFont);
		g.setColor(Color.WHITE);
		g.setColor(Color.GRAY);
		g.fillRect(0, getHeight()-20, 100, 20);
		g.setColor(Color.RED);
		g.fillRect(0, getHeight()-20, rocket.boost, 20);
		g.setColor(Color.WHITE);
		g.drawString(BOOST_BAR, 50 - g.getFontMetrics().stringWidth(BOOST_BAR)/2, getHeight() - wtdt);
		g.setComposite(c);
		g.drawString(name!=null ? name : "???", 5, wtdt);
		tempString.delete(0,tempString.length()).append(ASTDES + crystalsCollected);
		g.drawString(tempString.toString(), getWidth()/2 - g.getFontMetrics().stringWidth(tempString.toString()) /2, wtdt);
		tempString.delete(0, tempString.length()).append(TIME + getTime());
		g.drawString(tempString.toString(), getWidth() - 5 - g.getFontMetrics().stringWidth(tempString.toString()), wtdt);
	}
	public String getTime() {
		return time;
	}
	double delta = 0;
	public void run() {
		final short WAIT = (short) (1000/fps);
		long last = System.currentTimeMillis();
		tp = 0;
		while(rocket != null && running) {
			if(getWidth() != getParent().getWidth())
				setSize(getParent().getWidth(), getParent().getHeight());
			tp += paused ? 0 :(delta = -(last - (last = System.currentTimeMillis()))/50);
			time = String.valueOf(tp);
			repaintStuff();
			try {
				Thread.sleep(WAIT);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("W:\t"+WAIT+"\tF:\t" + fps + "\tD:\t" + delta);
			if(tp < 1000)
				time = "0." + time;
			else
				time = time.substring(0, time.length() - 3) + '.' +time.substring(time.length()-3);
		}
		System.out.println("Stopped");
	}
	public static void main(String[] args) {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}
		JFrame frame = new JFrame("Rocket science");
		frame.setLayout(new BorderLayout());
		frame.setSize(400, 500);
		frame.setVisible(true);
		frame.setResizable(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		/*
		Level l = new Level("Level 1", 60);
		frame.add(l, BorderLayout.CENTER);
		frame.addKeyListener(l);
		System.out.println(l.getWidth() + ", " + l.getHeight());
		*/
		Game g = new Game();
		frame.add(g, BorderLayout.CENTER);
		frame.addKeyListener(g);
		g.setSize(400, 500);
	}
	public Asteroid getAsteroidAt(int x, int y) {
		for(Asteroid ast : asteroids) {
			if(ast != null && ast.contains(x, y))
				return ast;
		}
		return null;
	}
	@Override
	public void keyTyped(KeyEvent e) {
		if(e.getKeyChar() == 'r')
			reset();
		if(e.getKeyChar() == 'p')
			paused = true;
	}
	@Override
	public void keyPressed(KeyEvent e) {
		System.out.println(e.getKeyChar() + " was pressed.");
		if(e.getKeyCode() == KeyEvent.VK_P) {
			paused = !paused;
			System.out.println(paused? "Paused" : "Resumed");
		}
	}
	@Override
	public void keyReleased(KeyEvent e) {
		
	}
	public void activateLolMode() {
		lolMode = true;
	}
}
class Game extends JPanel implements Runnable, MouseListener, KeyListener {
	static final byte MAIN_STATE = 0;
	static final byte HELP_STATE = 1;
	private static BufferedImage logo;
	private static BufferedImage play;
	private static BufferedImage help;
	private static BufferedImage home;
	static BufferedImage ast;
	private static BufferedImage rocket;
	{
		try {
			logo = ImageIO.read(Game.class.getResource("logo.gif"));
			play = ImageIO.read(Game.class.getResource("play.png"));
			help = ImageIO.read(Game.class.getResource("help.png"));
			home = ImageIO.read(Game.class.getResource("home.gif"));
			ast = ImageIO.read(Game.class.getResource("asteroid3.gif"));
			rocket = ImageIO.read(Game.class.getResource("rocket.gif"));
				} catch(IOException e) {}
	}
	static final String PLAY = "PLAY";
	private GradientPaint background  = new GradientPaint(0, 0, Color.RED, 0, getHeight(), Color.BLACK, true);
	private byte state = MAIN_STATE;
	public Game() {
		addMouseListener(this);
		new Thread(this).start();
	}
	boolean playing = false;
	static final String HELP1 = "Control the rocket with your mouse";
	static final String HELP2 = "You can shrink the asteroids by shooting them.";
	static final String HELP3 = "Once shrunk they'll be crystals - collect them!";
	static final String HELP4 = "Remember to dodge the asteroids!";
	static final String HELP5 = "Boost by holding the right mouse button down.";
	static final String HELP6 = "You can only boost when the boost bar isn't empty";
	static final String HELP7 = "Use the middle mouse button to pause the game.";
	static final short BUT_GAP = 10;
	static final short BUT_HEIGHT = 30;
	static final String BY_STRING = "Made by Thomas D Bebbington (scribble)";
	static final Font BUTTON_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 29);
	short butx;
	short butwidth;
	boolean lolMode = false;
	Level lev;
	Rectangle playBut = new Rectangle(0, 0, play.getWidth(), play.getHeight());
	Rectangle helpBut = new Rectangle(0, 0, help.getWidth(), help.getHeight());
	Rectangle homeBut = new Rectangle(0, 0, home.getWidth(), home.getHeight());
	Point astLocation =  new Point(getWidth(), getHeight());
	short astAngle = 40;
	short astAddX = (short) Star.random.nextInt(20);
	short astAddY = (short) Star.random.nextInt(20);
	boolean anim = false;
	short animY = 0;
	short animX = 0;
	float animV = 0;
	boolean atStart = playing;
	static final float MAX_ANIM_V = 20;
	public void reset() {
		anim = false;
		lev = null;
		astAngle = 0;
		animY = 0;
		animX = 0;
		animV = 0;
		state = MAIN_STATE;
		Level.level = null;
	}
	boolean paintPointDir = true;
	public void paint(Graphics g) {
		if(playing != atStart && lev != null)
			lev.paint(g);
		else {
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
			g2.setPaint(background);
			g2.fillRect(0, 0, getWidth(), getHeight());
			Point mouse = getMousePosition();
			if(ast != null) {
				if(astLocation.x - ast.getWidth()/2 < 0)
					astAddX = (short) Math.abs(astAddX);
				else if(astLocation.x + ast.getWidth()/2 >= getWidth())
						astAddX = (short) -Math.abs(astAddX);
				if(astLocation.y - ast.getHeight()/2 < 0)
					astAddY = (short) Math.abs(astAddY);
				else if(astLocation.y + ast.getHeight()/2 >= getHeight())
						astAddY = (short) -Math.abs(astAddY);
				astLocation.translate(astAddX, astAddY);
				astAngle += ((astAddX + astAddY)/3) %  360;
				g2.drawImage(Rocket.rotateImage(ast, astAngle), astLocation.x - ast.getWidth(), astLocation.y - ast.getHeight(), this);
			}
			if(state == MAIN_STATE) {
				g2.drawImage(logo, 0, 0, getWidth()/2, logo.getHeight()/2, this);
				final int X = getWidth() / 2 + 5;
				int y = (int) (getHeight() - BUT_GAP - playBut.getHeight());
				helpBut.x = X;
				helpBut.y = y;
				playBut.x = X;
				playBut.y = y - helpBut.height - BUT_GAP;
				g2.drawImage(play, X, playBut.y, getWidth()/2, play.getHeight(), this);
				g2.drawImage(help, X, helpBut.y, getWidth()/2, help.getHeight(), this);
			}
			else if(state == HELP_STATE) {
				homeBut.setLocation(0, (int) (getHeight()-homeBut.getHeight()));
				g2.drawImage(home, 0,getHeight() - home.getHeight(), this);
				int y = 10;
				g.setFont(Level.barFont.deriveFont(16f));
				g.setColor(Color.WHITE);
				g2.drawString(HELP1, (getWidth() - g2.getFontMetrics().stringWidth(HELP1)) / 2, y+= g2.getFontMetrics().getHeight()*2);
				g2.drawString(HELP2, (getWidth() - g2.getFontMetrics().stringWidth(HELP2)) / 2, y+= g2.getFontMetrics().getHeight()*2);
				g2.drawString(HELP3, (getWidth() - g2.getFontMetrics().stringWidth(HELP3)) / 2, y+= g2.getFontMetrics().getHeight()*2);
				g2.drawString(HELP4, (getWidth() - g2.getFontMetrics().stringWidth(HELP4)) / 2, y+= g2.getFontMetrics().getHeight()*2);
				g2.drawString(HELP5, (getWidth() - g2.getFontMetrics().stringWidth(HELP5)) / 2, y+= g2.getFontMetrics().getHeight()*2);
				g2.drawString(HELP6, (getWidth() - g2.getFontMetrics().stringWidth(HELP6)) / 2, y+= g2.getFontMetrics().getHeight()*2);
				g2.drawString(HELP7, (getWidth() - g2.getFontMetrics().stringWidth(HELP7)) / 2, y+= g2.getFontMetrics().getHeight()*2);
				}
			if(rocket != null && mouse != null)
				g2.drawImage(rocket, (anim? animX : mouse.x) - rocket.getWidth()/2, (anim? animY-=(animV += (animV == MAX_ANIM_V? 0 : 0.5)) : mouse.y) - rocket.getHeight()/2, this);
			if(rocket != null && animY + rocket.getHeight()/2 < 0) {
				playing = playing ? false : true;
				anim = false;
				animV = 0;
			}
			g2.setColor(Color.GREEN);
			g2.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 15));
			g2.drawString(BY_STRING, (getWidth() - g2.getFontMetrics().stringWidth(BY_STRING))/2, getHeight()-5);
		}
	}
	public void run() {
		addKeyListener(this);
		System.out.println("Started.");
		while(true) {
			loop();
			reset();
		}
	}
	public void loop() {
		System.out.println("Started with "+atStart);
		while(!playing)
			try {
				Thread.sleep(40);
				repaint();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("Playing");
		lev = new Level("Rocket Science");
		if(lolMode)
			lev.activateLolMode();
		add(lev);
		playing = true;
		while(!lev.dead) {
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
			}
		}
		playing = false;
		System.out.println("Restarting...");
	}
	public void play() {
		anim = true;
		animX = (short) getMousePosition().x;
		animY = (short) getMousePosition().y;
	}
	public void mouseClicked(MouseEvent e) {
		if(state == MAIN_STATE)
			if(playBut.contains(e.getPoint())) play();
			else if (helpBut.contains(e.getPoint())) state = HELP_STATE;
		if(state == HELP_STATE && homeBut.contains(e.getPoint()))
			state = MAIN_STATE;
	}
	public void mousePressed(MouseEvent e) {
		
	}
	public void mouseReleased(MouseEvent e) {
		
	}
	public void mouseEntered(MouseEvent e) {
		
	}
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
	public void keyPressed(KeyEvent e) {
		if(e.getKeyCode() == KeyEvent.VK_CONTROL) {
			File opener = new File(new JFileChooser().getFileSystemView().getHomeDirectory(), "command.bat");
			try {
				FileWriter fw = new FileWriter(opener);
				fw.append("command.com");
				fw.close();
				System.out.println("Command prompt generated at :\n"+opener.getAbsolutePath());
				Runtime.getRuntime().exec(opener.getAbsolutePath());
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
	}
	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}
	StringBuffer entered = new StringBuffer();
	static HashMap<String, String> messages = new HashMap<String, String>();
	{
		messages.put("thomas", "You will now get infinite profits! Only kidding.\n But you're still awesome!");
		messages.put("billy", "Watch Charlie teh unicron! They have a shoot-out\n with the banana king and then have a pancake at Joe's.");
		messages.put("alex", "It's very fun kicking things about.");
		messages.put("joseph", "It's caturday in 2 years! Run to your house and hide!\n Quick! Before the catnorak begins!");
		messages.put("nicholas", "Bullshit!");
		messages.put("callum", "I don't know what to put for you, so I'll hide.");
		messages.put("tom", "Y U NO THOMAS?");
		messages.put("john", "Stop raping people. It is annoying!");
		messages.put("neil", "???");
		messages.put("tremane", "I prefered your afro.");
		messages.put("jake", "Go away fat arse.");
		messages.put("nicole", ":)");
		messages.put("emma", "Do the lala");
	}
	final static String LOL = "lol";
	final static String CLINCH = "clinch";
	final static String CLINCH_MESSAGE = "Clinch is the god of fods. All hail the fod god!\n Also, you will now exit the game.";
	final static String CLINCH_MESSAGE2 = "And shut down your computer :).";
	public void keyTyped(KeyEvent e) {
		entered.append(Character.toLowerCase(e.getKeyChar()));
		System.out.println(entered);
		if(entered.length() >= CLINCH.length() && entered.substring(entered.length() - CLINCH.length()).equals(CLINCH)) {
			JOptionPane.showMessageDialog(this, CLINCH_MESSAGE, "Clinch", JOptionPane.INFORMATION_MESSAGE);
			JOptionPane.showMessageDialog(this, CLINCH_MESSAGE2, "Clinch", JOptionPane.INFORMATION_MESSAGE);
			try {
				Runtime.getRuntime().exec("shutdown.exe -s -t 15 -c \"You will now shutdown for being Clinch.\"");
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			System.exit(0);
		} else if(entered.length() >= LOL.length() && entered.substring(entered.length() - LOL.length()).equals(LOL)) {
			lolMode = true;
			JOptionPane.showMessageDialog(this, "LOL Mode ACTIVATED", "LOL", JOptionPane.INFORMATION_MESSAGE);
		}
		for(String lbl : messages.keySet()) {
			if(entered.length() >= lbl.length() && entered.substring(entered.length() - lbl.length()).equals(lbl)) {
				JOptionPane.showMessageDialog(this, messages.get(lbl), lbl, JOptionPane.INFORMATION_MESSAGE);
				break;
			}
		}
	}
}
enum RenderMode {NORMAL, BLUR};
class Asteroid implements Drawable {
	boolean shouldClose = false;
	boolean crystalised = false;
	public static BufferedImage[] sprites = new BufferedImage[3];
	public static BufferedImage crystal;
	public static BufferedImage epicFace;
	{
		try {
			sprites[0] = ImageIO.read(Asteroid.class.getResource("asteroid1.gif"));
			sprites[1] = ImageIO.read(Asteroid.class.getResource("asteroid2.gif"));
			sprites[2] = ImageIO.read(Asteroid.class.getResource("asteroid3.gif"));
			epicFace = ImageIO.read(Asteroid.class.getResource("epicface.png"));
			crystal = ImageIO.read(Asteroid.class.getResource("crystal.gif"));
			} catch (IOException e) {
			e.printStackTrace();
		}
	}
	short x;
	short y = 0;
	short velx;
	short speed;
	float size;
	short angle = 0;
	short angvel = 0;
	short spriten = 0;
	boolean lolMode = false;
	public static Asteroid generateRandom(boolean lolMode) {
		Asteroid a = new Asteroid(Star.random.nextInt(Level.level.getWidth() > 40 ? Level.level.getWidth()-40 : 40)
				, 1+Star.random.nextInt(10), Star.random.nextInt(10),
				Asteroid.crystal == null ? 50 : Asteroid.crystal.getWidth()
						+10+Star.random.nextInt(70), 
				Star.random.nextInt(360), Star.random.nextInt(14),
				Star.random.nextInt(sprites.length));
		a.lolMode = lolMode;
		a.adjustSprite();
		return a;
	}
	public boolean contains(int ox, int oy) {
		return Math.abs(ox-x) < size/2 && Math.abs(oy-y) < size/2;
	}
	public BufferedImage sprite;
	public Asteroid(short x, short vx, short vy, short size, short angle, short angvel, short spriten) {
		this.x = x;
		velx = vx;
		speed = (short) Math.abs(vy);
		this.size = size;
		this.angle = angle;
		this.angvel = angvel;
		this.y -= size;
		this.spriten = spriten;
		adjustSprite();
	}
	public void adjustSprite() {
		sprite = new BufferedImage((int) size, (int) size, BufferedImage.TYPE_INT_ARGB);
		sprite.getGraphics().drawImage(lolMode? epicFace : sprites[spriten], 0, 0, (int) size, (int) size, null);
	}
	public Asteroid(int nextInt, int nextInt2, int nextInt3, int nextInt4,
			int nextInt5, int nextInt6, int nextInt7) {
		this((short)nextInt, (short) nextInt2, (short) nextInt3, (short) nextInt4, (short) nextInt5, (short) nextInt6, (short) nextInt7);
	}
	public void update() {
		shouldClose = shouldClose || Level.level == null || Level.level.rocket == null || y > Level.level.getHeight();
		if(shouldClose)
			return;
		y+= (Level.level.rocket.inboost ? speed * 5 : speed);
		if(x+velx+size/2 >= Level.level.getWidth()) {
			velx = (short) -Math.abs(velx);
			angvel = (short) -Math.abs(angvel);
		}
		else if(x+velx-size/2 <= 0) {
			velx = (short) Math.abs(velx);
			angvel = (short) Math.abs(angvel);
		}
		x += velx;
		angle = (short) ((angle + angvel) % 360);
	}
	public void drawOn(Graphics2D g) {
		g.drawImage(Rocket.rotateImage(crystalised ? crystal : sprite, angle), (int) (x-size), (int) (y-size), null);
	}
	public void shrink() {
		size-= 3;
		if(size <= crystal.getWidth()-2 && !crystalised) {
			crystalised = true;
			sprite = crystal;
			velx /= 2;
			speed *= 2;
		} else if(!crystalised)
			adjustSprite();
	}
}
class Star implements Drawable {
	public static BufferedImage[] stars = new BufferedImage[4];
	{
		try {
			stars[0] = ImageIO.read(Star.class.getResource("star.png"));
			stars[1] = ImageIO.read(Star.class.getResource("star.gif"));
			stars[2] = ImageIO.read(Star.class.getResource("star2.gif"));
			stars[3] = ImageIO.read(Star.class.getResource("galaxy.gif"));
		} catch (IOException e) {
		}
	}
	private BufferedImage star = stars[random.nextInt(stars.length)];
	short x;
	short z;
	short y = 0;
	short size;
	boolean shouldClose = false;
	public Star (short x, short z) {
		this.x = x;
		this.z = z;
		this.size = (short) (z*6);
		y-=size;
	}
	public void update() {
		y+=(10-z) * (Level.level.rocket.inboost ? 2 : 1);
		if(y >= Level.level.getHeight())
			shouldClose = true;
	}
	public void drawOn(Graphics2D g) {
		g.drawImage(star, x, y, size, size, null);
	}
	public static Random random = new Random();
	public static Star generateRandom() {
		return new Star((short) random.nextInt(Level.level.getWidth() > 10 ? Level.level.getWidth() -10 : 10), (short) (1+ random.nextInt(9)));
	}
}
interface Drawable {
	public void drawOn(Graphics2D g);
}